from django.http import HttpResponse,HttpResponseRedirect
from django.shortcuts import render_to_response
from django.core.urlresolvers import reverse
from django.views.generic.create_update import update_object, create_object
from pentester.hosts.models import Host,Service,Configuration
from pentester.hosts.ifconfig import IFConfig
from metasploit import *

def ifaces(request):
    """
    Displays names of all network interfaces in the system.
    """
    ipiface = []                             #initialize interface list
    interfaces = IFConfig.get_ifaces_up()    #get list from IFConfig module
    
    # for every interface in a list create a string representing
    # interface with its settings (IP address and network mask)
    for iface in interfaces:                
        ipiface.append("%s (%s / %s)" % (iface, IFConfig.get_ip_address(iface), IFConfig.get_netmask(iface)))
    # join the list, separating interfaces with newline characters 
    output = '<br>\n'.join(ipiface)
    return HttpResponse("<b>Interfaces:</b><br> %s"% output)
def ifaceslist():
    """
    Gets list of network interfaces on the system and returns a list of 
    dictionaries with 'name', 'ip' and 'mask' keys. Works with conjunction
    on IFConfig module.
    """
    # initialize list of interfaces
    ipiface = []
    # fill it with entries from IFConfig module
    for iface in IFConfig.get_ifaces_up():
        ipiface.append({'name' : iface, 'ip' : IFConfig.get_ip_address(iface), 'mask' : IFConfig.get_netmask(iface)})
    return ipiface
def iface_detail(request, iface):
    """
    Display detailed information about particular network interface in the
    system.
    """
    
    interfaces = IFConfig.get_ifaces_up()
    
    if iface in interfaces: #check if interface is on the system and is up
        ip = IFConfig.get_ip_address(iface)
        mask = IFConfig.get_netmask(iface)
        return HttpResponse("Interface %s, <br>%s/%s" % (iface, ip, mask))
    else:
        return HttpResponse("error")
def index(request):
    """
    This view is used to render main application page. 
    All the work being done here is getting network interface list and
    creating code for navigation menu.
    """
    return render_to_response("index.html", { 'tresc' : 'Witaj', 'menuitems': createMenu('start'),
                                             'ifacelist' : ifaceslist()})
def createMenu(current):
    """
    Returns a dictionary of menu items. If 'current' argument matches 'name' property of
    particular menu item, it sets True, for 'current' property in dictionary.
    """
    menuitems = [
                 { 'name' : 'start', 'href' : '/'},
                 { 'name' : 'services', 'href' : '/services'},
                 { 'name' : 'results', 'href' : '/results'},
                 { 'name' : 'config', 'href' : '/config'},
                 { 'name' : 'logs', 'href' : '/logs/'},
                ]
    # iterate over menuitems, and sets menuitem['current']=True for
    # currently selected item (used to highlight menu item on the web interface)
    for menuitem in menuitems:
       if menuitem['name'] == current:
           menuitem['current'] = True
    return menuitems
def services(request,hostid=None):
    """ 
        Returns list of hosts correlated with services.
        If 'hostid' argument given, returns services of the particular host.
    """
    
    ret = []
    if not hostid: #all hosts
        for host in Host.objects.all():
            ret.append({
                        'address' : host.address, 'id' : host.id,
                        'services' : Service.objects.filter(host_id=host.id)
                        })
    else: # particular host (as specified by hostid arg.)
        ret[0] = {
                  'address' : Host.objects.get(id=hostid).address,
                  'services' : Service.objects.filter(host_id=hostid)
                 }
    return render_to_response("services.html",
                              { 
                               'menuitems' : createMenu("services"),
                               'hostservlist' : ret
                              })
def servupdate(request):
    """
       Updates services table.
       Sets service to 'up' state if serviceXX box is checked in POST request.
       Otherwise sets service to 'down' state. After saving changes, redirects
       user to service list view.
    """
    # walk through all services, check if corresponding checkbox is selected
    # and set proper state of the objects
    for serv in Service.objects.all():
        if not request.POST.has_key("service%s" % serv.id): # if checkbox not selected
            serv.state = 'down'
        else:
            serv.state = 'up'
        serv.save()
    return HttpResponseRedirect(reverse('pentester.hosts.views.services', args={'':None}))
def addport(request):
    """
        Adds user-specified service to services table in database.
    """
    try:
        host = request.POST['host']
        proto = request.POST['protocol']
        # check if 'protocol' parameter value is in
        # list of supported protocols
        if proto not in ['tcp', 'udp']:
            raise ValueError, "Incorrect protocol" 
        portnumber = request.POST['portnumber']
        # check if TCP/UDP port number value is in allowed range (0-65536) 
        if int(portnumber) > 65536 or int(portnumber) <= 0:
            raise ValueError, "Incorrect port number" 
        portdesc = request.POST['portdesc']
        # create a Service object, and store it in the database(model)
        Service(host_id=Host.objects.get(pk=host), proto=proto, port=portnumber, name=portdesc).save()
    except KeyError, e:
        return HttpResponse("Parameter error.")
    # after successful creation of the object, point user browser to view
    # with services list
    return HttpResponseRedirect(reverse('pentester.hosts.views.services', args={'':None}))
def configuration(request):
    """
        This view is used to create, display or edit configuration
        of our tool. Currently this view is used for setting path
        to local meta sploit framework, or setting the IP address and destination
        port of the remote meta sploit framework.
        This view is based on Django generic views. If configuration object
        does not exist in the database we create it. If exist, just display
        and update it.
    """
    # if Configuration object exists in the model, we use
    # Django's generic view (django.views.generic.create_update.update_object)
    try:
        p = Configuration.objects.get()
        return update_object(request,
                         model=Configuration,
                         object_id="1",
                         template_name="configuration.html",
                         post_save_redirect="/",
                         extra_context={ 'menuitems' : createMenu("config")}
                         )
    # else if Configuration object does not exist
    # it is probably first run, the database is  empty and
    # we should initialize the configuration by creating
    # object using django[...] generic view for creating objects.
    except Configuration.DoesNotExist:
        return create_object(request,
                         model=Configuration,
                         template_name="configuration.html",
                         post_save_redirect="/",
                         extra_context={ 'menuitems' : createMenu("config")}
                         )
def deletehost(request, hostid):
    """
    Deletes all services associated with particular host and host itself 
    from the database. Takes host ID as an argument. After deleting object
    from the model, redirects to the list of services.
    """
    Service.objects.filter(host_id=hostid).delete()
    Host.objects.filter(pk=hostid).delete()
    return HttpResponseRedirect("/services")   